package cn.edu.cqu.fredyvia.forum.config;

import cn.edu.cqu.fredyvia.forum.service.IUserService;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler;
import org.springframework.security.web.session.InvalidSessionStrategy;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 实现一个WebSecurityConfigurerAdapter然后重写一下configure方法，配置登录验证页、请求权限设置
 * 标识该类是配置类、开启 Security 服务、开启全局 Securtiy 注解
 */
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true) //启用基于注解的安全性 prePostEnable表示使用基于表达书的语法
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    IUserService iUserService;

    @Autowired
    DefaultInvalidSessionStrategy defaultInvalidSessionStrategy;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .logout()
                .logoutUrl("/user/logout")
                .deleteCookies("SESSION")
//                .logoutSuccessHandler();
                .invalidateHttpSession(true)
                .logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler(HttpStatus.OK))
                .and()
                .authorizeRequests() //安全请求策略，方法可有多个子节点matcher，每个matcher按照其声明顺序执行
                //页面访问权限控制说明
//                   .antMatchers("/thumb").permitAll()
//                    .antMatchers("/talk/add").permitAll()
                .antMatchers("/talk/info").permitAll()
                .antMatchers("/search").permitAll()
                .antMatchers("/talk/list").permitAll()
                .antMatchers("/talk/sortlist").permitAll()
                .antMatchers("/comment/list").permitAll()
                .antMatchers("/comment/oneinfo").permitAll()
                .antMatchers("/user/register").permitAll()
                .antMatchers("/user/exist").permitAll()
                .antMatchers("/user/login").permitAll()
//                .antMatchers("/user/logout").permitAll()
//                .antMatchers("/userinfo/detail").permitAll()
//                    .antMatchers("/user/upload").permitAll()
                .antMatchers("/captcha").permitAll()

                // 重要 druid的监控界面 网关需要过滤允许访问这个的ip
                .antMatchers("/druid/**").permitAll()
                .anyRequest().authenticated() //其它请求进行拦截（需要进行认证）
                //                .access("权限认证bean") 必须经过权限认证以后才能访问
//                .and()
//                .formLogin() //支持基于表单的登录验证
//                    .loginProcessingUrl("/api/login").permitAll()
//                    .successHandler(new UserAuthenticationSuccessHandler())
//                    .failureHandler(new UserAuthenticationFailureHandler())
                .and()
                .rememberMe().tokenValiditySeconds(600)
                .and()
                .cors().and()
                .csrf().disable(); //禁用CSRF保护

        http.sessionManagement().invalidSessionStrategy(defaultInvalidSessionStrategy).maximumSessions(1);
    }

    @Override
    @Bean
    //注入authenticationManager
    protected AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

//    /**
//     * 配置一个正常的验证
//     *
//     * @param auth
//     * @throws Exception
//     */
//    @Override
//    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//        //配置两个用户+密码+角色可验证成功（Java内存配置用户名和密码）
//        auth.authenticationProvider(authenticationProvider).userDetailsService(iUserService).passwordEncoder(passwordEncoder);
//    }
}

@Component
class DefaultInvalidSessionStrategy implements InvalidSessionStrategy {

    @Override
    public void onInvalidSessionDetected(HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {
        Cookie cookie = new Cookie("SESSION", null);
        cookie.setMaxAge(0);
        cookie.setPath("/api");
        String message = "session已失效";
        response.addCookie(cookie);
        response.setStatus(HttpStatus.UNAUTHORIZED.value());
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write(JSON.toJSONString(message));
    }
}